package crawl

import (
	"encoding/json"
	"fmt"
	"github.com/gocolly/colly"
	"github.com/gocolly/colly/proxy"
	"log"
	"math/rand"
	"regexp"
	"strings"
	"time"
	"wk/model"
)

const detailPrefix = `https://detail.1688.com/offer/`

/**
	userAgent 池
 */
var userAgentList = []string{"Mozilla/5.0 (compatible, MSIE 10.0, Windows NT, DigExt)",
	"Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, 360SE)",
	"Mozilla/4.0 (compatible, MSIE 8.0, Windows NT 6.0, Trident/4.0)",
	"Mozilla/5.0 (compatible, MSIE 9.0, Windows NT 6.1, Trident/5.0,",
	"Opera/9.80 (Windows NT 6.1, U, en) Presto/2.8.131 Version/11.11",
	"Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, TencentTraveler 4.0)",
	"Mozilla/5.0 (Windows, U, Windows NT 6.1, en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
	"Mozilla/5.0 (Macintosh, Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
	"Mozilla/5.0 (Macintosh, U, Intel Mac OS X 10_6_8, en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
	"Mozilla/5.0 (Linux, U, Android 3.0, en-us, Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
	"Mozilla/5.0 (iPad, U, CPU OS 4_3_3 like Mac OS X, en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
	"Mozilla/4.0 (compatible, MSIE 7.0, Windows NT 5.1, Trident/4.0, SE 2.X MetaSr 1.0, SE 2.X MetaSr 1.0, .NET CLR 2.0.50727, SE 2.X MetaSr 1.0)",
	"Mozilla/5.0 (iPhone, U, CPU iPhone OS 4_3_3 like Mac OS X, en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
	"MQQBrowser/26 Mozilla/5.0 (Linux, U, Android 2.3.7, zh-cn, MB200 Build/GRJ22, CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
}



var Spider *colly.Collector

type Crawl struct {

}

func init()  {
	Spider = colly.NewCollector(
		colly.MaxDepth(1),
		colly.UserAgent(RandomString()),
		colly.Async(true),
	)
	err := Spider.Limit(&colly.LimitRule{
		DomainGlob:  "*https.*",
		Parallelism: 2,
		Delay:       5 * time.Second,
	})

	if err != nil {
		log.Fatal(`limit set fail`, err)
	}

	rp, err := proxy.RoundRobinProxySwitcher("https://1.179.183.89:8080", "https://150.107.22.160:8080")
	if err != nil {
		log.Fatal(err)
	}
	Spider.SetProxyFunc(rp)

}

/**
	随机获取userAgent
 */
func RandomString() string {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	return userAgentList[r.Intn(len(userAgentList))]
}


/**
	interface to s
 */
func interface2String(inter interface{}) float64 {

	switch inter.(type) {

	case float64:
		return inter.(float64)

	default:
		return 0
	}

}

func (crawl Crawl)DoCrawl(url string,pageNum int )  {

	Spider.OnHTML(".offer-list-row", func(e *colly.HTMLElement) {
		e.ForEach(`li[data-offerid]`, func(i int, element *colly.HTMLElement) {
			detailUrl := detailPrefix + element.Attr("data-offerid") + ".html"
			fmt.Printf(detailUrl)
			time.Sleep(5*time.Second)
			// 访问详情页面
			//detailSpider(detailUrl)
		})

	})


	Spider.OnResponse(func(response *colly.Response) {

		fmt.Println(response.Headers.Get("resin-trace"))

		fmt.Println((response.StatusCode))

		fmt.Println(string(response.Body))
	})

	Spider.OnError(func(response *colly.Response, e error) {
		fmt.Println(e)
	})

	Spider.OnRequest(func(r *colly.Request) {
		fmt.Println("Visiting", r.URL)
		r.Headers.Set("Referer", url)
		r.Headers.Set("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3")
		r.Headers.Set("accept-language", "zh-CN,zh;q=0.9")
		r.Headers.Set("sec-fetch-mode", "navigate")
		r.Headers.Set("sec-fetch-site", "none")
		r.Headers.Set("sec-fetch-user", "?1")
	})



	for i := 1; i <= pageNum; i++ {
		Spider.Visit(fmt.Sprintf("%s?%s=%d", url, "pageNum", i))
	}

	Spider.Wait()

}

func detailSpider(detailUrl string)  {

	detail := Spider.Clone()

	detail.Visit(detailUrl)

	detail.OnHTML("body", func(e *colly.HTMLElement) {
		pNo := e.DOM.Find(`#mod-detail-attributes td:contains(货号)+td`).First().Text()
		// sku 信息
		e.ForEach(`div[data-widget-name=offerdetail_common_jsheader] .widget-custom-container script`, func(i int, element *colly.HTMLElement) {
			html, _ := element.DOM.Html()
			re := strings.Replace(html, "&#34;", `"`, -1)
			flysnowRegexp := regexp.MustCompile(`"skuMap":\{.*\}`)
			params := flysnowRegexp.FindStringSubmatch(re)

			//var sku string
			for _, param := range params {

				m := make(map[string]map[string]map[string]interface{})
				err := json.Unmarshal([]byte("{"+string(param)+"}"), &m)
				if err != nil {
					fmt.Println(err)
				} else {
					sku := m["skuMap"]
					for name, info := range sku {
						p := model.Product{}
						p.PNo = pNo
						index := strings.Index(name,"&")
						if index < 0  {
							p.Color = name
						}else {
							p.Color = name[:index]
						}

						for k, v := range info {
							if k == "canBookCount" {
								p.Stock = int(interface2String(v))
							}
						}
					}

				}

			}

		})

	})



	detail.OnResponse(func(response *colly.Response) {

	})
}